package bean;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;

import bean.vo.ItemOrdenPedidoVO;
import bean.vo.OrdenPedidoVO;


@Entity 
@Table( name = "ordenes_de_pedido" )
@SuppressWarnings({"unchecked"})
public class OrdenPedido extends EntidadPersistente{
	private Integer numeroPedido;
	private EstadoOrden estado;
	@OneToOne ( cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH} )
	@Cascade( org.hibernate.annotations.CascadeType.SAVE_UPDATE)
	private Cotizacion cotizacion;
	private Date fechaRecepcion;
	@OneToMany (cascade = CascadeType.ALL, mappedBy = "ordenPedido")
	private List<ItemOrdenPedido> itemsOrdenPedido;
	@ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH} )
	@Cascade( org.hibernate.annotations.CascadeType.SAVE_UPDATE)
	private Cliente cliente;
	
	public OrdenPedido () {
		this.itemsOrdenPedido = new ArrayList<ItemOrdenPedido>();
	}
	
	public OrdenPedido (Integer numeroPedido, Cliente cliente) {
		this.numeroPedido = numeroPedido;
		this.cliente = cliente;
	}
	
	public OrdenPedido (Integer numeroPedido, Cotizacion cotizacion, Date fechaRecepcion) {
		this.numeroPedido = numeroPedido;
		this.cotizacion = cotizacion;
		this.fechaRecepcion = fechaRecepcion;
		this.itemsOrdenPedido = new ArrayList<ItemOrdenPedido>();
		this.cliente = cotizacion.getCliente();
		this.estado = EstadoOrden.nuevo; 
	}
	
	public OrdenPedidoVO getVO() {
		OrdenPedidoVO vo = new OrdenPedidoVO();
		vo.setCliente(cliente != null ? cliente.getVO() : null);
		vo.setFechaRecepcion(fechaRecepcion);
		vo.setItemsOrdenPedido(new VOList<ItemOrdenPedidoVO>().getVoList(itemsOrdenPedido));
		vo.setNumeroPedido(numeroPedido);
		vo.setCotizacion(cotizacion != null ? cotizacion.getVO() : null);
		
		return vo;
	}
	
	public Integer getNumeroPedido() {
		return numeroPedido;
	}
	
	public void setNumeroPedido(Integer numeroPedido) {
		this.numeroPedido = numeroPedido;
	}
	
	public EstadoOrden getEstado() {
		return estado;
	}
	
	public void setEstado(EstadoOrden estado) {
		this.estado = estado;
	}
	
	public Cotizacion getCotizacion() {
		return cotizacion;
	}
	
	public void setCotizacion(Cotizacion cotizacion) {
		this.cotizacion = cotizacion;
	}
	
	public Date getFechaRecepcion() {
		return fechaRecepcion;
	}
	
	public void setFechaRecepcion(Date fechaRecepcion) {
		this.fechaRecepcion = fechaRecepcion;
	}
	
	public List<ItemOrdenPedido> getItemsOrdenPedido() {
		return itemsOrdenPedido;
	}
	
	public void setItemsOrdenPedido(List<ItemOrdenPedido> itemsOrdenPedido) {
		this.itemsOrdenPedido = itemsOrdenPedido;
	}
	
	public void agregarItem(Producto producto, Integer cantidad)
	{
		ItemOrdenPedido item = new ItemOrdenPedido(this, producto, cantidad);
		
		if (!itemsOrdenPedido.contains(item))
		{
			itemsOrdenPedido.add(item);
		}
	}
	
	public void eliminarItem(Producto producto)
	{
		ItemOrdenPedido item = new ItemOrdenPedido(this, producto, null);
		
		if (itemsOrdenPedido.contains(item))
		{
			itemsOrdenPedido.remove(item);
		}
	}
	
	@Override
	public int hashCode() {
		final int primo = 31;
		int result = 1;
		result = primo * (result + (numeroPedido == null ? 0 : numeroPedido.hashCode()) 
				+ (cliente == null ? 0 : cliente.hashCode()) );
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) return true;	
		if ((obj == null) || (!(obj instanceof OrdenPedido))) {
			return false;
		}
		
		OrdenPedido otro = (OrdenPedido) obj;
		
		boolean mismoCliente = (cliente!=null && otro.cliente != null ? (cliente.equals(otro.cliente)) : false);
		boolean mismoNumero = (numeroPedido!=null && otro.numeroPedido != null ? (numeroPedido.equals(otro.numeroPedido)) : false);
		
		return mismoCliente && mismoNumero;
	}

	public Cliente getCliente() {
		return cliente;
	}

	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}
}
